﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
//using System.ServiceModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Kaskelot.SP.UI.Analys.Data;
using Kaskelot.SP.UI.Analys.Domain;
using Kaskelot.SP.UI.Analys.ViewModel;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.TreeView;

namespace Kaskelot.SP.UI.Analys.Controls
{
    public partial class TreeContainer : UserControl
    {
        public event EventHandler<GenericEventArgs<List<Entity>>> EntitiesSelected = delegate { };
        public event EventHandler<GenericEventArgs<List<Field>>> FieldsUpdated = delegate { };

        public TreeContainer()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(TreeContainer_Loaded);
        }

        void TreeContainer_Loaded(object sender, RoutedEventArgs e)
        {
            GetData(delegate() { });
        }

        private void GetData(Action onSuccess)
        {
            EntityTree.ItemsSource = null;

            AnalyseServiceWrapper.Instance.GetEntities(
                //Success
                delegate(ObservableCollection<ViewModel.Entity> entities)
                {
                    EntityTree.ItemsSource = entities;
                    onSuccess();
                },
                //Error
                delegate(Exception ex)
                {
                    ErrorHandler.Instance.HandleError(ex);
                });
        }

        private void EntityTree_Checked(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {
            RadTreeViewItem treeItem = e.OriginalSource as RadTreeViewItem;
            if (treeItem.Item != null)
            {
                if (treeItem.Item is Field)
                {
                    Field f = treeItem.Item as Field;
                    f.Checked = true;
                    RaiseFieldsUpdatedEvent();
                    RadTreeViewItem parent = treeItem.ParentItem as RadTreeViewItem;
                    ((Entity)parent.Item).Checked = true;
                }
                else
                {
                    var currEntity = treeItem.Item as Entity;
                    currEntity.Checked = true;

                    DisableIncompatible(currEntity);

                    RaiseEntitiesUpdatedEvent();
                }
            }
        }

        private void DisableIncompatible(Entity currEntity)
        {
            EntityTree.Items.OfType<Entity>().Where(ent => currEntity.CannotBeCombinedWith.Any(name => name == ent.Name))
                .ToList().ForEach((Entity incompatibleEntity) =>
                {
                    incompatibleEntity.Checked = false;
                    incompatibleEntity.IsEnabled = false;
                    incompatibleEntity.Fields.ForEach((Field f) =>
                    {
                        f.Checked = false;
                    });
                });
        }

        private void RaiseFieldsUpdatedEvent()
        {
            FieldsUpdated(this, new GenericEventArgs<List<Field>>(
                GetCurrentFields()
                ));
        }

        public void SetCheckedItems(List<Entity> entities, List<Field> fields)
        {
            EntityTree.Items.OfType<Entity>().ToList().ForEach(delegate(Entity entity)
            {
                if (entities.Any(e => e.Name == entity.Name))
                {
                    entity.Checked = true;
                    entity.Expanded = true;
                    if (entity.CannotBeCombinedWith.Any())
                    {
                        DisableIncompatible(entity);
                    }

                    entity.Fields.ForEach((Field f) =>
                    {
                        if (fields.Any(qf => qf.InternalName == f.InternalName))
                            f.Checked = true;
                    });
                }
            });
        }

        public List<Field> GetCurrentFields()
        {
            List<Field> fields = new List<Field>();
            EntityTree.Items.OfType<Entity>().ToList().ForEach((Entity e) =>
                {
                    fields.AddRange(e.Fields.Where(f => f.Checked));
                });

            return fields;
        }

        public void Reset(Action onSuccess)
        {
            GetData(onSuccess);
        }

        public List<Entity> GetCurrentEntities()
        {
            return EntityTree.Items.OfType<Entity>().Where(e => e.Checked).ToList();
        }

        private void EntityTree_Unchecked(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {
            RadTreeViewItem treeItem = e.OriginalSource as RadTreeViewItem;
            if (treeItem.Item is Field)
            {
                Field f = treeItem.Item as Field;
                f.Checked = false;
                RaiseFieldsUpdatedEvent();
            }
            else
            {
                var currEntity = (treeItem.Item as Entity);
                currEntity.Checked = false;
                currEntity.Fields.ForEach((Field f) =>
                {
                    f.Checked = false;
                });

                if (currEntity.CannotBeCombinedWith.Any())
                {
                    EntityTree.Items.OfType<Entity>().ToList().ForEach((Entity ent) =>
                        {
                            ent.IsEnabled = true;
                        });
                }

                RaiseEntitiesUpdatedEvent();
            }
        }

        private void RaiseEntitiesUpdatedEvent()
        {
            List<Entity> allEntities = EntityTree.Items.OfType<Entity>().Where(item => item.Checked).ToList();
            EntitiesSelected(this, new GenericEventArgs<List<Entity>>(allEntities));
        }

        private void RadMenuItem_Click(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {
            //Entity selection = this.EntityContextMenu.GetClickedElement<RadTreeViewItem>().DataContext as Entity;

            //this.EntityTree.Items.Cast<Entity>().ToList().ForEach(delegate(Entity entity)
            //{
            //    entity.IsKeyEntity = false;
            //});

            //selection.IsKeyEntity = true;
        }

        //private void EntityContextMenu_Opened(object sender, RoutedEventArgs e)
        //{
        //    if (this.EntityContextMenu.GetClickedElement<RadTreeViewItem>().Item is Field)
        //        this.EntityContextMenu.Visibility = System.Windows.Visibility.Collapsed;
        //    else
        //        this.EntityContextMenu.Visibility = System.Windows.Visibility.Visible;
        //}
    }
}
